
#ifndef _UI_SYSTEM_
#define _UI_SYSTEM_

#include <cocos2d.h>
USING_NS_CC;

#include <map>
#include <stack>
#include <string>
#include <functional>

using namespace std;

class UISystem: public CCObject, public CCTargetedTouchDelegate {
public:
	static UISystem* getInstance();
	~UISystem(void);

	void init();

	void changLayout(CCNode* parent, const char* layoutFile);
	void addLayout(CCNode* parent, const char* layoutFile);
	void removeTopLayout();

	virtual bool ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent);
    virtual void ccTouchMoved(CCTouch *pTouch, CCEvent *pEvent);
    virtual void ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent);
    virtual void ccTouchCancelled(CCTouch *pTouch, CCEvent *pEvent);

    // 1. id - parent node id
    // 2. func - callback function
    void registerTouchHandler(int id, function<void (string const &)> func);

	// return true, means already created the node, return false, means uisystem should create the node
    // 1. id - parent node id
    // 2. func - callback function
    void registerNodeCreationHandler(int id, function<int(CCNode*, const string&, const CCRect&)> func);

	const string& getCurrentLayoutName() {
		return _currentLayoutName;
	}

private:
	static UISystem* _instance;
	UISystem(void);

	void loadScaleButtonDefinitions();
	void parseLayout(CCNode* parentNode, tinyxml2::XMLElement* parentItem);
	CCNode* createLabel(CCNode* parentNode, const string& key, const CCRect& rect, tinyxml2::XMLElement* item);
	CCNode* createSprite(CCNode* parentNode, const string& key, const CCRect& rect, tinyxml2::XMLElement* item);
	CCNode* createScale9Sprite(CCNode* parentNode, const string& key, const CCRect& rect, tinyxml2::XMLElement* item);
	unsigned int getTouchedNode(const CCPoint& pt, CCNode* parent);

private:
	map<string, CCRect> _mapScaleButtons;
	map<unsigned int, string> _mapNodeMapping;
	stack<CCLayer*> _layoutStack;

    typedef function<void(const string& key)>  EventHandlingFunction;
	typedef function<int(CCNode* parent, const string& key, const CCRect& rect)> NodeCreationHandlingFunction;

    map<unsigned int, EventHandlingFunction> _mapEventHandlers;
	map<unsigned int, NodeCreationHandlingFunction> _mapNodeCreationHandlers;

	string _currentLayoutName;
};

#endif
